package com.patrol.inspection.Controller;

import com.patrol.inspection.Entity.Location;
import com.patrol.inspection.Entity.MyGeo;
import com.patrol.inspection.Utils.JsonUtils;
import org.elasticsearch.action.delete.DeleteRequest;
import org.elasticsearch.action.index.IndexRequest;
import org.elasticsearch.action.search.SearchRequest;
import org.elasticsearch.action.search.SearchResponse;
import org.elasticsearch.action.update.UpdateRequest;
import org.elasticsearch.client.RequestOptions;
import org.elasticsearch.client.RestHighLevelClient;
import org.elasticsearch.common.geo.GeoDistance;
import org.elasticsearch.common.geo.GeoPoint;
import org.elasticsearch.common.unit.DistanceUnit;
import org.elasticsearch.common.xcontent.XContentType;
import org.elasticsearch.index.query.BoolQueryBuilder;
import org.elasticsearch.index.query.QueryBuilders;
import org.elasticsearch.search.SearchHit;
import org.elasticsearch.search.builder.SearchSourceBuilder;
import org.elasticsearch.search.sort.FieldSortBuilder;
import org.elasticsearch.search.sort.SortBuilders;
import org.elasticsearch.search.sort.SortOrder;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.PageRequest;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;

import java.io.IOException;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;

@RestController
@RequestMapping("/es")
public class ESController {
    @Autowired
    private RestHighLevelClient restHighLevelClient;

    /**
     * 查询所有
     */
    @RequestMapping("/get")
    public String get(@RequestParam("distance") int distance) throws IOException {
        // 1.准备Request
        SearchRequest request = new SearchRequest("my_geo");
        String location = "39.93031708627304,116.4470385453491";

        request.source().sort(SortBuilders
                .geoDistanceSort("location", new GeoPoint(location))
                .order(SortOrder.ASC)
                .unit(DistanceUnit.KILOMETERS)
        );
        SearchResponse response = restHighLevelClient.search(request, RequestOptions.DEFAULT);

        // 将结果转成对象
        List<MyGeo> resList = new ArrayList<>();
        for (SearchHit hit : response.getHits().getHits()) {
            resList.add(JsonUtils.convertJsonToObject(hit.getSourceAsString(), MyGeo.class));
        }
        System.out.println(resList);


        return response.toString();
    }

    /**
     * 范围查询
     */
    @RequestMapping("/get-data-by-distance")
    public String getDataByDistance(@RequestParam("distance") int distance) throws IOException {
// 1.准备Request
        SearchRequest request = new SearchRequest("my_geo");
        SearchSourceBuilder searchSourceBuilder = new SearchSourceBuilder();
        searchSourceBuilder.query(QueryBuilders.geoDistanceQuery("location")
                .point(39.93031708627304,116.4470385453491)
                .distance(distance + "km"));
        request.source(searchSourceBuilder);
        SearchResponse response1 = restHighLevelClient.search(request, RequestOptions.DEFAULT);
        System.out.println(response1);


        return response1.toString();
    }

    /***
     * 范围查询并排序
     */
    @RequestMapping("/get-sort-data-by-distance")
    public String getSortDataByDistance(@RequestParam("distance") int distance) throws IOException {
// 1.准备Request
        SearchRequest request = new SearchRequest("my_geo");
        SearchSourceBuilder searchSourceBuilder = new SearchSourceBuilder();
        searchSourceBuilder.query(QueryBuilders.geoDistanceQuery("location")
                .point(39.93031708627304,116.4470385453491)
                .distance(distance + "km"));
        searchSourceBuilder.sort(
                SortBuilders.geoDistanceSort("location", 39.93031708627304,116.4470385453491)
                        .order(SortOrder.ASC)
                        .unit(DistanceUnit.KILOMETERS)
        );
        request.source(searchSourceBuilder);
        SearchResponse response1 = restHighLevelClient.search(request, RequestOptions.DEFAULT);
        System.out.println(response1);


        return response1.toString();
    }

    /**
     * 范围查询并通过时间过滤将结果排序
     */
    @RequestMapping("/getSortDataByDistanceAndTimeRange")
    public String getSortDataByDistanceAndTimeRange(@RequestParam("distance") int distance) throws IOException {
        SearchRequest request = new SearchRequest("my_geo");
        // 构建查询
        BoolQueryBuilder boolQueryBuilder = QueryBuilders.boolQuery();
        boolQueryBuilder.must(QueryBuilders.rangeQuery("createTime").gte( "2024-05-01 00:00:00").lte("2024-05-31 00:00:00"));
        boolQueryBuilder.must(QueryBuilders.geoDistanceQuery("location")
                .point(39.93031708627304,116.4470385453491)
                .distance(distance + "km"));
        SearchSourceBuilder searchSourceBuilder = new SearchSourceBuilder();
        searchSourceBuilder.query(boolQueryBuilder);
        searchSourceBuilder.sort(
                SortBuilders.geoDistanceSort("location", 39.93031708627304,116.4470385453491)
                        .order(SortOrder.ASC)
                        .unit(DistanceUnit.KILOMETERS)
        );

        request.source(searchSourceBuilder);
        SearchResponse response1 = restHighLevelClient.search(request, RequestOptions.DEFAULT);
        return response1.toString();
    }

    @RequestMapping("/add")
    public String add() throws IOException {
        MyGeo newDAta = MyGeo.builder()
                .type("0")
                .id(106)
                .createTime("2024-06-11 00:00:00")
                .location(new Location(45.611032, 126.489358))
                .build();
        String json = JsonUtils.convertObjToJSON(newDAta);
        System.out.println(json);

        // 1.准备Request
        IndexRequest request = new IndexRequest("my_geo");
        // 2.准备请求参数DSL，其实就是文档的JSON字符串
        request.source(json, XContentType.JSON);
        request.type("_doc");
        // 3.发送请求
        restHighLevelClient.index(request, RequestOptions.DEFAULT);
        return "ok";
    }

    @RequestMapping("/delete")
    void testDeleteDocumentById(@RequestParam("id") String id ) throws IOException {
        // 1.准备Request      // DELETE /hotel/_doc/{id}
        DeleteRequest request = new DeleteRequest("my_geo");
        request.id(id);
        request.type("_doc");
        // 2.发送请求
        restHighLevelClient.delete(request, RequestOptions.DEFAULT);
    }

    @RequestMapping("/update")
    void testUpdateById(@RequestParam("id") String id ) throws IOException {
        // 1.准备Request
        UpdateRequest request = new UpdateRequest("my_geo","_doc",id);
        // 2.准备参数
        request.doc(
                "type", "1"
        );
        // 3.发送请求
        restHighLevelClient.update(request, RequestOptions.DEFAULT);
    }
}
